home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Libris Britannia 4
/
science library(b).zip
/
science library(b)
/
COMMUNIC
/
2500.ZIP
/
WKERMIT.ZIP
/
WIN19T.C
< prev
next >
Wrap
C/C++ Source or Header
|
1990-11-19
|
28KB
|
1,134 lines
/*
* Windows H19 Terminal Emulator
*
* Written by William S. Hall
* 3665 Benton Street, #66
* Santa Clara, CA 95051
*
* Terminal and status window module
*/
#define NOKANJI
#define NOATOM
#include <string.h>
#include <windows.h>
#include "winasc.h"
#include "winh19.h"
#include "win19d.h"
/* local functions */
static void NEAR MoveCursorLeft(PTWND pTW, WORD count);
static void NEAR MoveCursorRight(PTWND pTW, WORD count);
static void NEAR SetScroll(void);
static void NEAR MoveCursorUp(PTWND pTW, WORD count);
static void NEAR MoveCursorDown(PTWND pTW, WORD count);
static void NEAR PositionCursorRow(PTWND, short);
static void NEAR PositionCursorCol(PTWND, short);
static void NEAR CursorHome(PTWND);
static void NEAR DeleteChar(PTWND, WORD);
static void NEAR ClearStatusLine(PTWND);
static void NEAR ClearTermWindow(PTWND);
static void NEAR SlapScreenToClip(PTWND);
static void NEAR SetAttrib(HDC, int);
static void NEAR H19HideCaret(HWND hWnd);
static void NEAR H19ShowCaret(HWND hWnd);
static void NEAR SaveCursor(short line, short column);
static void NEAR GetCursor(short lines, short cols, LONG lParam);
static int NEAR H19TerminalDisplay(PTWND, BYTE *, short);
static void NEAR DoCR(PTWND);
static void NEAR DoBS(PTWND);
static void NEAR MakeCaret(PTWND);
static void NEAR DoHT(PTWND);
static void NEAR ClearToEndOfLine(PTWND);
static void NEAR ClearToEndOfScreen(PTWND);
static void NEAR StatWndPaint(PTWND, LPPAINTSTRUCT);
static void NEAR ClearToScreenTop(PTWND);
static void NEAR ClearToLineStart(PTWND);
static void NEAR EraseEntireLine(PTWND);
static void NEAR TermWndPaint(PTWND, LPPAINTSTRUCT);
static void NEAR AdjustWindowToCursor(PTWND);
static void NEAR ShowLineOfText(HDC, short, short, BYTE *, short, short);
static void NEAR InsertLine(PTWND, WORD);
static void NEAR DeleteLine(PTWND, WORD);
static void NEAR ReverseLF(PTWND);
static void NEAR DoLF(PTWND);
/* status window proc */
long FAR PASCAL StatWndProc(hWnd,message,wParam,lParam)
HWND hWnd;
unsigned message;
WORD wParam;
LONG lParam;
{
PAINTSTRUCT ps;
int count;
register PTWND pSW = (PTWND)GetWindowWord(hWnd, 0);
switch(message) {
case WH19_COMMAND:
if (CD.StatOpen) {
H19HideCaret(hWnd);
switch (wParam) {
case H19_MOVECURSORRIGHT:
MoveCursorRight(pSW, LOWORD(lParam));
break;
case H19_MOVECURSORLEFT:
MoveCursorLeft(pSW, LOWORD(lParam));
break;
case H19_POSITIONCURSORCOL:
PositionCursorCol(pSW, (short)LOWORD(lParam));
break;
case H19_DELETECHAR:
DeleteChar(pSW, LOWORD(lParam));
break;
case H19_CLRSCREEN:
ClearStatusLine(pSW);
break;
case H19_CLRTOENDOFLINE:
case H19_CLRTOENDOFSCREEN:
ClearToEndOfLine(pSW);
break;
case H19_CLRTOSTARTOFLINE:
case H19_CLRTOTOPOFSCREEN:
ClearToLineStart(pSW);
break;
case H19_INSERTLINE:
case H19_DELETELINE:
pSW->Xpos = pSW->CurLineOffset = 0;
case H19_ERASELINE:
EraseEntireLine(pSW);
break;
}
SetCaretPos(pSW->Xpos, pSW->CharHeight);
H19ShowCaret(hWnd);
}
break;
case WH19_CARETFUNCTION:
switch(wParam) {
case H19_SHOWCARET:
H19ShowCaret(hWnd);
break;
case H19_HIDECARET:
H19HideCaret(hWnd);
break;
case H19_CREATECARET:
if (lParam) {
MakeCaret(pSW);
SetCaretPos(pSW->Xpos, pSW->Ypos + pSW->CharHeight);
if (CD.StatOpen)
H19ShowCaret(hWnd);
}
break;
case H19_DESTROYCARET:
if (lParam) {
H19HideCaret(hWnd);
DestroyCaret();
}
break;
}
break;
case WH19_STRINGINPUT:
count = 0;
if (CD.StatOpen) {
H19HideCaret(hWnd);
count = H19TerminalDisplay(pSW, (BYTE *)LOWORD(lParam),
(short)wParam);
SetCaretPos(pSW->Xpos, pSW->CharHeight);
H19ShowCaret(hWnd);
}
return((LONG)count);
case WH19_CURSORPOSITION:
if (wParam == H19_SAVECURSOR)
SaveCursor(TW.MaxLines, pSW->CurLineOffset);
else
GetCursor(TW.MaxLines, pSW->CurLineOffset, lParam);
break;
case WM_CREATE:
TermWndCreate(hWnd, lParam);
break;
case WM_PAINT:
BeginPaint(hWnd, (LPPAINTSTRUCT)&ps);
if (!IsRectEmpty((LPRECT)&ps.rcPaint))
StatWndPaint(pSW, (LPPAINTSTRUCT)&ps);
EndPaint(hWnd, (LPPAINTSTRUCT)&ps);
break;
default:
return ((long)DefWindowProc(hWnd,message,wParam,lParam));
}
return(0L);
}
/* terminal window procedure */
long FAR PASCAL TermWndProc(HWND hWnd,unsigned message,WORD wParam,LONG lParam)
{
PAINTSTRUCT ps;
short lines;
int count;
register PTWND pTW = (PTWND)GetWindowWord(hWnd, 0);
switch(message) {
case WH19_COMMAND:
H19HideCaret(hWnd);
switch (wParam) {
case H19_MOVECURSORRIGHT:
MoveCursorRight(pTW, LOWORD(lParam));
break;
case H19_MOVECURSORLEFT:
MoveCursorLeft(pTW, LOWORD(lParam));
break;
case H19_MOVECURSORUP:
MoveCursorUp(pTW, LOWORD(lParam));
break;
case H19_MOVECURSORDOWN:
MoveCursorDown(pTW, LOWORD(lParam));
break;
case H19_POSITIONCURSORROW:
PositionCursorRow(pTW, (short)LOWORD(lParam));
break;
case H19_POSITIONCURSORCOL:
PositionCursorCol(pTW, (short)LOWORD(lParam));
break;
case H19_ADJUSTWINDOW:
AdjustWindowToCursor(pTW);
break;
case H19_CURSORHOME:
CursorHome(pTW);
break;
case H19_DELETECHAR:
DeleteChar(pTW, LOWORD(lParam));
break;
case H19_CLRSCREEN:
ClearTermWindow(pTW);
break;
case H19_CLRTOENDOFSCREEN:
ClearToEndOfScreen(pTW);
case H19_CLRTOENDOFLINE:
ClearToEndOfLine(pTW);
break;
case H19_CLRTOTOPOFSCREEN:
ClearToScreenTop(pTW);
case H19_CLRTOSTARTOFLINE:
ClearToLineStart(pTW);
break;
case H19_ERASELINE:
EraseEntireLine(pTW);
break;
case H19_REVERSELINEFEED:
ReverseLF(pTW);
break;
case H19_INSERTLINE:
InsertLine(pTW, LOWORD(lParam));
break;
case H19_DELETELINE:
DeleteLine(pTW, LOWORD(lParam));
break;
}
SetCaretPos(pTW->Xpos, pTW->Ypos + pTW->CharHeight);
H19ShowCaret(hWnd);
break;
case WH19_CARETFUNCTION:
switch(wParam) {
case H19_SHOWCARET:
H19ShowCaret(hWnd);
break;
case H19_HIDECARET:
H19HideCaret(hWnd);
break;
case H19_CREATECARET:
if (lParam) {
AdjustWindowToCursor(pTW);
MakeCaret(pTW);
SetCaretPos(pTW->Xpos, pTW->Ypos + pTW->CharHeight);
H19ShowCaret(hWnd);
}
break;
case H19_DESTROYCARET:
if (lParam) {
H19HideCaret(hWnd);
DestroyCaret();
}
break;
}
break;
case WH19_STRINGINPUT:
H19HideCaret(hWnd);
count = H19TerminalDisplay(pTW, (BYTE *)LOWORD(lParam),
(short)wParam);
SetCaretPos(pTW->Xpos, pTW->Ypos + pTW->CharHeight);
H19ShowCaret(hWnd);
return((LONG)count);
case WH19_CURSORPOSITION:
lines = (pTW->oCurrentLine - pTW->oTopLine) / pTW->MaxCols;
if (lines < 0)
lines += pTW->MaxLines;
if (wParam == H19_SAVECURSOR)
SaveCursor(lines, pTW->CurLineOffset);
else
GetCursor(lines, pTW->CurLineOffset, lParam);
break;
case WH19_SLAPSCREEN:
SlapScreenToClip(pTW);
break;
case WM_CREATE:
TermWndCreate(hWnd, lParam);
break;
case WM_PAINT:
BeginPaint(hWnd, (LPPAINTSTRUCT)&ps);
if (!IsRectEmpty((LPRECT)&ps.rcPaint))
TermWndPaint(pTW, (LPPAINTSTRUCT)&ps);
EndPaint(hWnd, (LPPAINTSTRUCT)&ps);
break;
default:
return ((long)DefWindowProc(hWnd,message,wParam,lParam));
}
return(0L);
}
/* copy screen to clipboard */
static void NEAR SlapScreenToClip(PTWND pTW)
{
short cols = pTW->MaxCols;
short lines = pTW->MaxLines;
HANDLE hGlob = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,
(LONG)((cols + 2) * lines + 2));
if (hGlob != NULL) {
RECT rect;
BYTE *pTop = pTW->pVidBuffer;
BYTE *lineptr = pTop + pTW->oTopLine;
BYTE *pEnd = pTop + pTW->oVidLastLine;
BYTE FAR *pGlob = GlobalLock(hGlob);
short count;
register int i, j;
BYTE ch;
BYTE *pSource;
GetClientRect(pTW->hWnd, &rect);
InvertRect(pTW->hDC, &rect);
for (i = 0; i < lines; i++) {
count = cols;
while ((*(lineptr + count - 1) == SP) && (count > 0))
count--;
pSource = lineptr;
for (j = 0; j < count; j++) {
ch = (*pSource++) & 0x7f;
if (ch == DEL)
ch -= 1;
else if (ch < SP)
ch += '^';
*pGlob++ = ch;
}
*pGlob++ = '\r';
*pGlob++ = '\n';
if ((lineptr += cols) > pEnd)
lineptr = pTop;
}
*pGlob = NUL;
GlobalUnlock(hGlob);
if (OpenClipboard(pTW->hWnd)) {
EmptyClipboard();
SetClipboardData(CF_TEXT, hGlob);
CloseClipboard();
}
else
GlobalFree(hGlob);
InvertRect(pTW->hDC, &rect);
}
}
/* update the status window */
static void NEAR StatWndPaint(PTWND pSW, LPPAINTSTRUCT ps)
{
BYTE *pBuf = pSW->pVidBuffer;
short xpos = 0;
short count = pSW->MaxCols;
register short left = ps->rcPaint.left;
register short right = pSW->Width - ps->rcPaint.right;
short cwidth = pSW->CharWidth;
short countchange;
if (ps->rcPaint.top < pSW->CharHeight) {
if (left >= cwidth) {
xpos = left - left % cwidth;
countchange = left / cwidth;
pBuf += countchange;
count -= countchange;
}
if (right >= cwidth)
count -= right / cwidth;
ShowLineOfText(ps->hdc,xpos,0,pBuf,count,cwidth);
}
}
/* update the terminal window */
static void NEAR TermWndPaint(PTWND pTW, LPPAINTSTRUCT ps)
{
register int i;
BYTE *pTop = pTW->pVidBuffer;
BYTE *lineptr = pTop + pTW->oTopLine;
BYTE *pEnd = pTop + pTW->oVidLastLine;
short cwidth = pTW->CharWidth;
short cheight = pTW->CharHeight;
short line1 = 0;
short line2 = pTW->MaxLines;
short cols = pTW->MaxCols;
short count = cols;
register short base = 0;
short left = ps->rcPaint.left;
short right = pTW->Width - ps->rcPaint.right;
short top = ps->rcPaint.top;
short bottom = pTW->Height - ps->rcPaint.bottom;
short xpos = 0;
short offset = 0;
short countchange;
if (left >= cwidth) {
xpos = left - left % cwidth;
countchange = left / cwidth;
offset += countchange;
count -= countchange;
}
if (right >= cwidth)
count -= right / cwidth;
if (top >= cheight) {
line1 = top / cheight;
base += line1 * cheight;
lineptr += line1 * cols;
if (lineptr > pEnd)
lineptr = pTop + (lineptr - pEnd) - cols;
}
if (bottom >= cheight)
line2 -= bottom / cheight;
for (i = line1; i < line2; i++) {
ShowLineOfText(ps->hdc,xpos,base,lineptr+offset,count,cwidth);
base += cheight;
if ((lineptr += cols) > pEnd)
lineptr = pTop;
}
}
/* display a line of text on terminal or status window */
static void NEAR ShowLineOfText(hDC, Xpos, Ypos, lineptr, linewidth, charwidth)
HDC hDC;
short Xpos, Ypos;
BYTE *lineptr;
short linewidth, charwidth;
{
register int i,j;
short X;
BYTE *sptr, *eptr, ch;
BYTE pBuf[TERMMAXCOLS];
i = 0;
X = Xpos;
sptr = eptr = lineptr;
while (i < linewidth) {
for (j = 0; j < linewidth - i; j++)
if (*eptr++ > DEL)
break;
SetAttrib(hDC, NORMAL);
TextOut(hDC,X,Ypos,(LPSTR)sptr, j);
if ((i += j) >= linewidth)
break;
sptr = --eptr;
X += j * charwidth;
for (j = 0; j < linewidth - i; j++)
if ((ch = *eptr++) <= DEL)
break;
else
pBuf[j] = ch & 0x7f;
SetAttrib(hDC, REVERSE);
TextOut(hDC,X,Ypos,(LPSTR)pBuf,j);
if ((i += j) < linewidth) {
X += j * charwidth;
sptr = --eptr;
}
}
}
/* cursor support routines */
static void NEAR MoveCursorRight(PTWND pTW, WORD count)
{
register short *offset = &pTW->CurLineOffset;
register short *xpos = &pTW->Xpos;
short cols = pTW->MaxCols - 1;
short width = pTW->CharWidth;
while ((*offset < cols) && (count--)) {
*offset += 1;
*xpos += width;
}
}
static void NEAR MoveCursorLeft(PTWND pTW, WORD count)
{
register short *offset = &pTW->CurLineOffset;
register short *xpos = &pTW->Xpos;
short width = pTW->CharWidth;
while((*offset > 0) && (count--)) {
*offset -= 1;
*xpos -= width;
}
}
static void NEAR MoveCursorUp(PTWND pTW, WORD count)
{
register short *oCurLine = &pTW->oCurrentLine;
short top = pTW->oTopLine;
if (*oCurLine != top) {
register short *ypos = &pTW->Ypos;
short cols = pTW->MaxCols;
short cheight = pTW->CharHeight;
while ((*oCurLine != top) && (count--)) {
*ypos -= cheight;
if ((*oCurLine -= cols) < 0)
*oCurLine = pTW->oVidLastLine;
}
AdjustWindowToCursor(pTW);
}
}
static void NEAR MoveCursorDown(PTWND pTW, WORD count)
{
register short *oCurLine = &pTW->oCurrentLine;
short bottom = pTW->oBottomLine;
if (*oCurLine != bottom) {
register short *ypos = &pTW->Ypos;
short cols = pTW->MaxCols;
short cheight = pTW->CharHeight;
short last = pTW->oVidLastLine;
while ((*oCurLine != bottom) && (count--)) {
*ypos += cheight;
if ((*oCurLine += cols) > last)
*oCurLine = 0;
}
AdjustWindowToCursor(pTW);
}
}
/* position window so that cursor is visible */
static void NEAR AdjustWindowToCursor(PTWND pTW)
{
POINT point;
HWND hWnd = pTW->hWnd;
short ypos = pTW->Ypos;
short width = pTW->Width;
short cheight = pTW->CharHeight;
register short Y1 = MW.SCTopTextLine;
register short Y2 = MW.SCBottomTextLine;
short Y;
if ((CD.StatOpen) && (CD.StatOverlayTerm))
Y2 -= cheight;
point.x = pTW->Xpos;
point.y = ypos;
ClientToScreen(hWnd, (POINT FAR *)&point);
Y = point.y;
if (Y < Y1) {
MoveWindow(hWnd,0,-ypos, width, pTW->Height, FALSE);
ScrollWindow(hWnd,0,Y1-Y, (LPRECT)NULL, (LPRECT)NULL);
UpdateWindow(hWnd);
}
else if (Y > Y2) {
MoveWindow(hWnd, 0, Y2-Y1-ypos, width, pTW->Height, FALSE);
ScrollWindow(hWnd,0,Y2-Y, (LPRECT)NULL, (LPRECT)NULL);
UpdateWindow(hWnd);
}
}
/* display a string */
static int NEAR H19TerminalDisplay(PTWND pTW, BYTE *str, short len)
{
register BYTE *ptr;
register short ctr;
short toff, txpos;
BYTE *tBuf;
BYTE savebuf[TERMMAXCOLS];
HWND hWnd = pTW->hWnd;
HDC hDC = pTW->hDC;
short cols = pTW->MaxCols;
short cwidth = pTW->CharWidth;
short width = pTW->Width;
BYTE *pBuf = pTW->pVidBuffer;
short more_than_one_line = pTW->MaxLines - 1;
while (len) {
ptr = str;
ctr = 0;
tBuf = pBuf + pTW->oCurrentLine;
toff = pTW->CurLineOffset;
txpos = pTW->Xpos;
while ((*ptr >= SP) && (*ptr < DEL)) {
if ((len) && (toff < cols)) {
if (CD.GraphicsMode)
if (*ptr == '~')
*ptr += 1;
else if (*ptr >= '^')
*ptr -= '^';
if (CD.ICToggle)
savebuf[ctr] = *(tBuf + toff);
*(tBuf + toff++) = *ptr++ | CD.CharAttribute;
ctr += 1;
txpos += cwidth;
len -= 1;
}
else
break;
}
if (ctr) {
if (CD.ICToggle) {
RECT rect;
short ypos = pTW->Ypos;
short xpos = pTW->Xpos;
short tomove, tocopy;
tomove = cols - toff -ctr;
tocopy = min (ctr, cols - toff);
if (tomove > 0) {
memmove(tBuf + toff + ctr, tBuf + toff, tomove);
if (tocopy > 0)
strncpy(tBuf + toff, savebuf, tocopy);
}
SetRect(&rect, xpos, ypos, width, ypos + pTW->CharHeight);
ScrollWindow(hWnd, txpos - xpos, 0, &rect, &rect);
UpdateWindow(hWnd);
}
else {
if (CD.InverseVideo)
SetAttrib(hDC, REVERSE);
else
SetAttrib(hDC, NORMAL);
TextOut(hDC, pTW->Xpos, pTW->Ypos, (LPSTR)str, ctr);
}
if (toff < cols) {
pTW->CurLineOffset = toff;
pTW->Xpos = txpos;
}
else {
if (CD.WrapAround) {
DoCR(pTW);
if (more_than_one_line)
DoLF(pTW);
}
else {
pTW->CurLineOffset = cols - 1;
pTW->Xpos = width - cwidth;
}
}
}
while ((*ptr < SP) || (*ptr >= DEL)) {
if (len) {
switch (*ptr) {
case BEL:
MessageBeep(0);
break;
case HT:
DoHT(pTW);
break;
case BS:
DoBS(pTW);
break;
case LF:
if (CD.CRonLF)
DoCR(pTW);
if (more_than_one_line)
DoLF(pTW);
break;
case CR:
DoCR(pTW);
if (CD.HoldScreen &&
(pTW->oCurrentLine == pTW->oBottomLine)) {
if (CD.ReleaseCount == 0) {
SetScroll();
return(len > 0 ? len - 1 : 0);
}
else
CD.ReleaseCount -= 1;
}
if (CD.LFonCR)
if (more_than_one_line)
DoLF(pTW);
break;
}
len -= 1;
ptr++;
}
else
break;
}
str = ptr;
}
return(len);
}
/* hold screen support */
static void NEAR SetScroll()
{
BYTE keystate[256];
GetKeyboardState((LPSTR)keystate);
keystate[VK_SCROLL] |= 1;
SetKeyboardState((LPSTR)keystate);
CD.ScrollLock = TRUE;
}
/* control character modules */
static void NEAR DoLF(PTWND pTW)
{
HWND hWnd = pTW->hWnd;
register short cols = pTW->MaxCols;
register oEnd = pTW->oVidLastLine;
if ( (pTW->oCurrentLine += cols) > oEnd)
pTW->oCurrentLine = 0;
if (pTW->oCurrentLine == pTW->oTopLine) {
if ((pTW->oTopLine += cols) > oEnd)
pTW->oTopLine = 0;
if ((pTW->oBottomLine += cols) > oEnd)
pTW->oBottomLine = 0;
memset(pTW->pVidBuffer + pTW->oCurrentLine, SP, cols);
ScrollWindow(hWnd,0,-pTW->CharHeight, (LPRECT)NULL, (LPRECT)NULL);
UpdateWindow(hWnd);
}
else
pTW->Ypos += pTW->CharHeight;
AdjustWindowToCursor(pTW);
}
static void NEAR DoCR(PTWND pTW)
{
pTW->Xpos = pTW->CurLineOffset = 0;
}
static void NEAR DoBS(PTWND pTW)
{
if (pTW->CurLineOffset) {
pTW->CurLineOffset -= 1;
pTW->Xpos -= pTW->CharWidth;
}
}
static void NEAR DoHT(PTWND pTW)
{
register short offset = pTW->CurLineOffset;
if (offset < pTW->MaxCols - 1) {
short charwidth = pTW->CharWidth;
short limit = pTW->TabLimit;
register short xpos = pTW->Xpos;
do {
xpos += charwidth;
} while((++offset % DEF_TABSTOP != 0) && (offset < limit));
pTW->Xpos = xpos;
pTW->CurLineOffset = offset;
}
}
/* caret creation and deletion routines */
static void NEAR MakeCaret(PTWND pTW)
{
register short height;
if (CD.BlockCursor)
height = -pTW->CharHeight;
else
height = -2;
CreateCaret(pTW->hWnd, (HBITMAP)NULL, pTW->CharWidth, height);
}
static void NEAR H19ShowCaret(HWND hWnd)
{
if (!CD.CursorOff)
ShowCaret(hWnd);
}
static void NEAR H19HideCaret(HWND hWnd)
{
if (!CD.CursorOff)
HideCaret(hWnd);
}
/* set text attributes */
static void NEAR SetAttrib(HDC hDC, int type)
{
switch (type) {
case NORMAL:
SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
SetBkColor(hDC, GetSysColor(COLOR_WINDOW));
break;
case REVERSE:
SetTextColor(hDC, GetSysColor(COLOR_WINDOW));
SetBkColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
break;
}
}
/* cursor positioning routines */
static void NEAR PositionCursorRow(PTWND pTW, short y)
{
register short cols = pTW->MaxCols;
register short oCurr = pTW->oTopLine;
pTW->Ypos = y * pTW->CharHeight;
oCurr += y * cols;
if (oCurr > pTW->oVidLastLine)
oCurr -= pTW->ScreenSize;
pTW->oCurrentLine = oCurr;
AdjustWindowToCursor(pTW);
}
static void NEAR PositionCursorCol(PTWND pTW, short x)
{
/*
if (x >= pTW->MaxCols)
x = pTW->MaxCols - 1;
*/
pTW->Xpos = x * pTW->CharWidth;
pTW->CurLineOffset = x;
}
static void NEAR CursorHome(PTWND pTW)
{
pTW->Xpos = pTW->Ypos = pTW->CurLineOffset = 0;
pTW->oCurrentLine = pTW->oTopLine;
AdjustWindowToCursor(pTW);
}
/* character deletion */
static void NEAR DeleteChar(PTWND pTW, WORD count)
{
RECT rect;
short cols = pTW->MaxCols;
short offset = pTW->CurLineOffset;
BYTE *dest = pTW->pVidBuffer + pTW->oCurrentLine + offset;
HWND hWnd = pTW->hWnd;
short ypos = pTW->Ypos;
register short copycount;
register short maxdelchars;
if (count > (maxdelchars = cols - offset))
count = maxdelchars;
copycount = maxdelchars - count;
memmove(dest, dest + count, copycount);
memset(dest+copycount, SP, count);
SetRect(&rect, pTW->Xpos, ypos, pTW->Width, ypos + pTW->CharHeight);
ScrollWindow(hWnd,-pTW->CharWidth * count,0, &rect, &rect);
UpdateWindow(hWnd);
}
/* clear screen routines */
static void NEAR ClearStatusLine(PTWND pSW)
{
RECT rect;
register HWND hWnd = pSW->hWnd;
memset(pSW->pVidBuffer, SP, pSW->MaxCols);
SetRect((LPRECT)&rect,0,0,pSW->Width,pSW->CharHeight);
InvalidateRect(hWnd, (LPRECT)&rect, TRUE);
UpdateWindow(hWnd);
}
static void NEAR ClearTermWindow(PTWND pTW)
{
RECT rect;
register HWND hWnd = pTW->hWnd;
memset(pTW->pVidBuffer, SP, pTW->ScreenSize);
pTW->Xpos = pTW->Ypos = pTW->CurLineOffset = 0;
pTW->oCurrentLine = pTW->oTopLine = 0;
pTW->oBottomLine = pTW->oVidLastLine;
SetRect((LPRECT)&rect,0,0,pTW->Width,pTW->Height);
InvalidateRect(hWnd, (LPRECT)&rect, TRUE);
UpdateWindow(hWnd);
AdjustWindowToCursor(pTW);
}
static void NEAR ClearToEndOfLine(PTWND pTW)
{
RECT rect;
HWND hWnd = pTW->hWnd;
register offset = pTW->CurLineOffset;
register char *src = pTW->pVidBuffer + pTW->oCurrentLine + offset;
memset(src, SP, pTW->MaxCols - offset);
SetRect(&rect, pTW->Xpos, pTW->Ypos, pTW->Width, pTW->Ypos+pTW->CharHeight);
InvalidateRect(hWnd, (LPRECT)&rect, TRUE);
UpdateWindow(hWnd);
}
static void NEAR ClearToEndOfScreen(PTWND pTW)
{
RECT rect;
char *pBuf = pTW->pVidBuffer;
char *pEnd = pBuf + pTW->oVidLastLine;
char *pBottom = pBuf + pTW->oBottomLine;
register char *base = pBuf + pTW->oCurrentLine;
register short cols = pTW->MaxCols;
do {
if ((base += cols) > pEnd)
base = pBuf;
memset(base, SP, cols);
} while (base != pBottom);
SetRect(&rect, 0, pTW->Ypos + pTW->CharHeight, pTW->Width, pTW->Height);
InvalidateRect(pTW->hWnd, (LPRECT)&rect, TRUE);
UpdateWindow(pTW->hWnd);
}
static void NEAR ClearToLineStart(PTWND pTW)
{
HWND hWnd = pTW->hWnd;
BYTE *pCurr = pTW->pVidBuffer + pTW->oCurrentLine;
RECT rect;
register short ypos = pTW->Ypos;
register offset = pTW->CurLineOffset + 1;
memset(pCurr, SP, offset);
SetRect(&rect, 0, ypos, offset * pTW->CharWidth, ypos + pTW->CharHeight);
InvalidateRect(hWnd, (LPRECT)&rect, TRUE);
UpdateWindow(hWnd);
}
static void NEAR ClearToScreenTop(PTWND pTW)
{
RECT rect;
HWND hWnd = pTW->hWnd;
BYTE *pBuf = pTW->pVidBuffer;
BYTE *pTop = pBuf + pTW->oTopLine;
BYTE *pEnd = pBuf + pTW->oVidLastLine;
register BYTE *base = pBuf + pTW->oCurrentLine;
register short cols = pTW->MaxCols;
do {
if ((base -= cols) < pBuf)
base = pEnd;
memset(base, SP, cols);
} while (base != pTop);
SetRect((LPRECT)&rect, 0, 0, pTW->Width, pTW->Ypos);
InvalidateRect(hWnd, (LPRECT)&rect, TRUE);
UpdateWindow(hWnd);
}
static void NEAR EraseEntireLine(PTWND pTW)
{
RECT rect;
register HWND hWnd = pTW->hWnd;
register short ypos = pTW->Ypos;
memset(pTW->pVidBuffer + pTW->oCurrentLine, SP, pTW->MaxCols);
SetRect((LPRECT)&rect, 0, ypos, pTW->Width, ypos + pTW->CharHeight);
InvalidateRect(hWnd, (LPRECT)&rect, TRUE);
UpdateWindow(hWnd);
}
/* reverse index */
static void NEAR ReverseLF(PTWND pTW)
{
register short cols = pTW->MaxCols;
register short oEnd = pTW->oVidLastLine;
if ((pTW->oCurrentLine -= cols) < 0)
pTW->oCurrentLine = oEnd;
if (pTW->oCurrentLine == pTW->oBottomLine) {
if ((pTW->oTopLine -= cols) < 0)
pTW->oTopLine = oEnd;
if ((pTW->oBottomLine -= cols) < 0)
pTW->oBottomLine = oEnd;
memset(pTW->pVidBuffer + pTW->oCurrentLine, SP, cols);
ScrollWindow(pTW->hWnd,0,pTW->CharHeight,(LPRECT)NULL,(LPRECT)NULL);
UpdateWindow(pTW->hWnd);
}
else
pTW->Ypos -= pTW->CharHeight;
AdjustWindowToCursor(pTW);
}
/* line insertion and deletion routines */
static void NEAR InsertLine(PTWND pTW, WORD count)
{
RECT rect;
int i;
HWND hWnd = pTW->hWnd;
short cols = pTW->MaxCols;
short lines = pTW->MaxLines;
BYTE *pBuf = pTW->pVidBuffer;
BYTE *pCurr = pBuf + pTW->oCurrentLine;
BYTE *pEnd = pBuf + pTW->oVidLastLine;
register BYTE *dest = pBuf + pTW->oBottomLine;
register BYTE *src;
if (count > lines)
count = lines;
if ((src = dest - count * cols) < pBuf)
src += pTW->ScreenSize;
while (dest != pCurr) {
memmove(dest, src, cols);
if ((src -= cols) < pBuf)
src = pEnd;
if ((dest -= cols) < pBuf)
dest = pEnd;
}
src = pCurr;
for (i = 0; i < count; i++) {
memset(src, SP, cols);
if ((src += cols) > pEnd)
src = pBuf;
}
pTW->CurLineOffset = pTW->Xpos = 0;
SetRect((LPRECT)&rect, 0, pTW->Ypos, pTW->Width, pTW->Height);
ScrollWindow(hWnd, 0, count * pTW->CharHeight, &rect, &rect);
UpdateWindow(hWnd);
}
static void NEAR DeleteLine(PTWND pTW, WORD count)
{
RECT rect;
HWND hWnd = pTW->hWnd;
short cols = pTW->MaxCols;
BYTE *pBuf = pTW->pVidBuffer;
BYTE *dest = pBuf + pTW->oCurrentLine;
BYTE *pBottom = pBuf + pTW->oBottomLine;
register BYTE *pEnd = pBuf + pTW->oVidLastLine;
register BYTE *src;
int i;
if (count > pTW->MaxLines)
count = pTW->MaxLines;
if ((src = dest + count * cols) > pEnd)
src -= pTW->ScreenSize;
while (dest != pBottom) {
memmove(dest, src, cols);
if ((src += cols) > pEnd)
src = pBuf;
if ((dest += cols) > pEnd)
dest = pBuf;
}
src = pBottom;
for (i = 0; i < count; i++) {
memset(src, SP, cols);
if ((src -= cols) < pBuf)
src = pEnd;
}
pTW->CurLineOffset = pTW->Xpos = 0;
SetRect((LPRECT)&rect,0,pTW->Ypos,pTW->Width,pTW->Height);
ScrollWindow(hWnd,0, -count * pTW->CharHeight, &rect, &rect);
UpdateWindow(hWnd);
}
/* cursor save and restore */
static void NEAR SaveCursor(short line, short column)
{
CD.CurSaveRow = line;
CD.CurSaveCol = column;
}
static void NEAR GetCursor(short lines, short cols, LONG lParam)
{
short *x, *y;
x = (short *)LOWORD(lParam);
y = (short *)HIWORD(lParam);
*x = lines;
*y = cols;
}